//! 直接寻址的 内存, 不支持页表之类的东西
use crate::memory::{self, MemoryRawData};

use std::mem::size_of;

use tracing::trace;

pub struct DirMemory<const BASE: usize> {
    data: Vec<u8>,
}

impl<const BASE: usize> DirMemory<BASE> {
    pub fn new(size: usize) -> Self {
        let data = vec![0; size];
        Self { data }
    }
    fn guest_to_host(addr: usize) -> usize {
        addr - BASE
    }
}

/// 为了方(偷)便(懒)，所有的get和set指令，在不带后缀的情况下，都是小端字节序
impl<const BASE: usize> memory::Memory for DirMemory<BASE> {
    const BASE: usize = BASE;

    fn len(&self) -> usize {
        self.data.len()
    }

    fn vaddr_get<T: MemoryRawData>(&self, addr: usize) -> T {
        self.paddr_get::<T>(addr)
    }

    fn paddr_get<T: MemoryRawData>(&self, addr: usize) -> T {
        let offset = Self::guest_to_host(addr);
        let data_len = size_of::<T>();
        if offset + data_len > self.data.len() {
            panic!(
                "read invalid memory, mem size: {}, access addr: {}, len: {}",
                self.data.len(),
                offset,
                data_len
            );
        }
        unsafe { *(self.data.as_ptr().add(offset) as *const T) }
    }

    fn vaddr_write<T: MemoryRawData>(&mut self, addr: usize, data: T) {
        self.paddr_write(addr, data)
    }

    fn paddr_write<T: MemoryRawData>(&mut self, addr: usize, data: T) {
        let offset = Self::guest_to_host(addr);
        let data_len = size_of::<T>();
        trace!(write_addr = offset);
        if offset + data_len > self.data.len() {
            panic!(
                "write invalid memory, mem size: {}, access addr: {}, len: {}",
                self.data.len(),
                offset,
                data_len
            );
        }
        unsafe {
            *(self.data.as_mut_ptr().add(offset) as *mut T) = data;
        }
    }
}
